package psn.kiko.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import psn.kiko.pojo.R;
import psn.kiko.pojo.entity.FileEntity;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 2024/11/30 17:06
 */
@Service
public class FileService{
	/**
	 * 文件上传根目录
	 */
	@Value("${file.uploadDirString}")
	private String uploadDirString;
	@Value("${file.mapping}")
	private String fileMapping;
	
	/**
	 * 文件上传
	 * @param uploadedFile 要保存的文件
	 */
	public R<?> uploadFile(MultipartFile uploadedFile){
		String failMsg = "文件上传失败";
		if(uploadedFile == null||uploadedFile.isEmpty()){
			return R.failWithMsgAndData(failMsg,"文件不能为空");
		}
		try{
			//检查、创建文件保存目录
			File uploadDir = new File(uploadDirString);
			if(!uploadDir.exists()){
				if(!uploadDir.mkdirs()){
					return R.failWithMsgAndData(failMsg,"无法在服务器创建文件保存目录");
				}
			}
			
			String fileStoreName = getFileStoreName(uploadedFile);
			Path targetPath = Paths.get(uploadDir.getAbsolutePath(),fileStoreName);
			//保存到磁盘
			Files.copy(uploadedFile.getInputStream(),targetPath);
			//生成文件访问uri
			String fileUri = ServletUriComponentsBuilder.fromCurrentContextPath()
					.path(fileMapping)
					.path(fileStoreName)
					.toUriString();
			//文件信息封装
			FileEntity data = FileEntity.builder()
					.size(uploadedFile.getSize())
					.originalName(uploadedFile.getOriginalFilename())
					.showName(uploadedFile.getOriginalFilename())
					.type(uploadedFile.getContentType())
					.uploadDateTime(LocalDateTime.now())
					.storeName(fileStoreName)
					.uri(fileUri)
					.absolutePath(targetPath.toFile().getAbsolutePath())
					.build();
			return R.okWithMsgAndData("文件上传成功",data);
		}catch(FileAlreadyExistsException e){
			e.printStackTrace();
			return R.failWithMsgAndData(failMsg,"文件已存在");
		}catch(IOException e){
			e.printStackTrace();
			return R.failWithMsgAndData(failMsg,e.getMessage());
		}
	}
	
	private String getFileStoreName(MultipartFile file){
		String originalFilename = file.getOriginalFilename();
		assert originalFilename != null;
		int lastIndexOfDot = originalFilename.lastIndexOf('.');
		String fileExtension = originalFilename.substring(lastIndexOfDot);
		return UUID.randomUUID()+fileExtension;
	}
	
	
	/**
	 * 文件下载
	 * @param shortFileName 需要下载的文件简短名
	 */
	public ResponseEntity<Resource> downloadFile(String shortFileName){
		Path filePath = Paths.get(uploadDirString).resolve(shortFileName).normalize();
		try{
			Resource resource = new UrlResource(filePath.toUri());
			if(resource.exists()||resource.isReadable()){
				return ResponseEntity.ok()
						.contentType(MediaType.APPLICATION_OCTET_STREAM)
						.header(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename=\""+resource.getFilename()+"\"")
						.body(resource);
			}else{
				return ResponseEntity.notFound().build();
			}
		}catch(IOException ex){
			ex.printStackTrace();
			return ResponseEntity.status(500).build();
		}
	}
	
	/**
	 * 扫描已上传的文件，将未入库的文件信息入库，将数据库有记录而磁盘上不存在对应文件的记录从数据库删除
	 */
	public R<?> scanAndStore(){
		//todo
		//如果根目录都不存在，那么清空文件数据库信息
		return null;
	}
	
}
